package snafu.framework.states;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import snafu.framework.senses.stimuli.Stimulus;
import snafu.framework.senses.stimuli.StimulusItself;
import snafu.framework.states.literals.StateLiteral;
import snafu.framework.states.literals.StateLiteralItself;
import snafu.framework.view.Access;
import snafu.framework.view.ViewFactory;

public class StateItself extends AbstractState implements ViewFactory<StateView> {
	/** The literals defining the state. */
	protected List<StateLiteralItself<?>> literals;
	protected Set<StimulusItself> stimuli;
	
	/**
	 * Instantiates a new state with an empty list of literals.
	 */
	public StateItself() {
		literals = new ArrayList<StateLiteralItself<?>>();
		stimuli = new HashSet<StimulusItself>();
	}
	
	/**
	 * Returns a copy of all literals.
	 */
	@Override
	public List<StateLiteral<?>> getLiterals() {
		List<StateLiteral<?>> newLiterals = new ArrayList<StateLiteral<?>>();
		for (StateLiteralItself<?> literal : literals) {
			newLiterals.add(literal);
		}
		return newLiterals;
	}
	
	/**
	 * Adds the given literal to the list of literals.
	 */
	public void addLiteral(StateLiteralItself<?> literal) {
		literals.add(literal);
	}
	
	/**
	 * Sets the given literal as unique. This means that all literals with the same class as the
	 * given literal are removed from the list of literals and the given one will be added.
	 * 
	 * @param literal
	 *            the new unique literal
	 */
	public void setLiteral(StateLiteralItself<?> literal) {
		removeLiterals(literal.getClass());
		addLiteral(literal);
	}
	
	/**
	 * Removes the literal from the list of literals.
	 * 
	 * @param literal
	 *            the literal to remove
	 */
	public void removeLiteral(StateLiteral<?> literal) {
		literals.remove(literal);
	}
	
	/**
	 * Removes all literals that have the given class.
	 * 
	 * @param <L>
	 *            a class extending StateLiteral
	 * @param clazz
	 *            the class of the literals to remove
	 */
	public <L extends StateLiteral<?>> void removeLiterals(Class<L> clazz) {
		for (StateLiteral<?> literal : getLiterals(clazz)) {
			removeLiteral(literal);
		}
	}
	
	public void addStimulus(StimulusItself stimulus) {
		stimuli.add(stimulus);
	}
	
	@Override
	public Set<Stimulus> getStimuli() {
		Set<Stimulus> newStimuli = new HashSet<Stimulus>();
		
		for (Stimulus stimulus : stimuli) {
			newStimuli.add(stimulus);
		}
		
		return newStimuli;
	}
	
	@Override
	public StateView createView(Access access) {
		return new StateView(access, this);
	}
}
